﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using ProgramMain.Classifiers;
using ProgramMain.Database;
using ProgramMain.Database.SimpleOpticNetDBTableAdapters;
using ProgramMain.Google;
using ProgramMain.NetVis;

namespace ProgramMain.Layers
{
    public class ShiftConnection : EventArgs
    {
        public Point PointOld { get; private set; }
        public Point PointNew { get; private set; }
        public ShiftConnection(Point pointOld, Point pointNew)
        {
            PointOld = pointOld;
            PointNew = pointNew;
        }
    }

    public delegate int DCalckHorizont(FibreRange fibreRange1, FibreRange fibreRange2);

    public class VisLayer
    {

        public int ZoomCcale { get; private set; }
        public bool AllConnection { get; set; }

        private List<EquipmentSerializer> EquipmentXml;
        private List<LineConnectionRange> ConnectionXml;

        private int _PlanType;
        public int PlanType
        {
            get { return _PlanType; }
            set
            {
                _PlanType = value;
                ZeroPoint = Point.Empty;
                Plan = null;
            }
        }

        public double Scale
        { get { return ZoomCcale / 10.0; } }

        public void SetZoom(int zoom)
        {
            ZoomCcale = zoom;
        }

        public Point ZeroPoint { get; set; }
        public bool IsPrint { get; private set; }
        public Point GetLocation(Point virtualPoint)
        {
            #region для принтера
            if (IsPrint)
            {
                Rectangle r = GetPlanRectangle();
                Point print = new Point((int)r.Left, (int)r.Top) + new Size(-10, -10);
                print.X = Math.Abs(print.X);
                print.Y = Math.Abs(print.Y);

                return new Point(
                  (int)(virtualPoint.X + print.X),
                  (int)(virtualPoint.Y + print.Y));
            }
            #endregion

            return new Point(
                    (int)(virtualPoint.X * Scale + ZeroPoint.X),
                    (int)(virtualPoint.Y * Scale + ZeroPoint.Y));
        }

        public Point GetVirtual(Point locationPoint)
        {
            if (Scale == 0) return Point.Empty;
            return new Point((int)Math.Round((locationPoint.X - ZeroPoint.X) / Scale, 0),
                             (int)Math.Round((locationPoint.Y - ZeroPoint.Y) / Scale, 0)
                             );
        }
        private void AddEquipments(CrossBoxVis equipment)
        {

            if (equipment.CurveElementKindID == 2 || equipment.CurveElementKindID == 3)
            {
                equipment.IndexMap =
                    (from q in _curveElements where q.CurveElementKindID == 2 || q.CurveElementKindID == 3 select q).Count();
            }
            if (equipment.CurveElementKindID == 1)
            {
                equipment.IndexMap = (from q in _curveElements where q.CurveElementKindID == 1 select q).Count();
            }
            _curveElements.Add(equipment);

            //  ZeroPoint = PlanToCenter();
        }

        private int? _VertexID;

        private List<RangeBase> Ranges = new List<RangeBase>();

        private List<LineConnectionRange> connectionLine = new List<LineConnectionRange>();

        private List<CrossBoxVis> _curveElements = new List<CrossBoxVis>();

        public CrossBoxVis FindLocation(int index, int kindID)
        {
            CrossBoxVis res = null;
            try
            {
                if (index - 4 > -1)
                {
                    if (kindID == 1)
                    {
                        res = (from q in _curveElements where q.CurveElementKindID == kindID select q).ToList()[index - 4];
                    }
                    if (kindID == 2 || kindID == 3)
                    {
                        res = (from q in _curveElements where q.CurveElementKindID == 2 || q.CurveElementKindID == 3 select q).ToList()[index - 4];
                    }
                }

            }
            catch (Exception)
            {
            }
            return res;
        }

        public int CurveElementCount()
        {
            return (from q in _curveElements where q.CurveElementKindID == 2 || q.CurveElementKindID == 3 select q).Count();
        }
        public EquipmentSerializer GetMapProperty(int id)
        {
            if (EquipmentXml == null) return null;
            IEnumerable<EquipmentSerializer> e = from q in EquipmentXml where q.ID == id select q;
            if (e.Count() == 0) return null;
            return e.First();
        }

        public LineConnectionRange GetConnectionFromXmlByFibreID(int fibre1id, int fibre2id)
        {
            if (ConnectionXml == null) return null;
            IEnumerable<LineConnectionRange> e = from q in ConnectionXml
                                                 where (q.Fibre1ID == fibre1id && q.Fibre2ID == fibre2id) || (q.Fibre2ID == fibre1id && q.Fibre1ID == fibre2id)
                                                 select q;
            if (e.Count() == 0) return null;
            return e.First();
        }

        public void DeSerializeLineConnection(string data)
        {
            if (string.IsNullOrEmpty(data))
            {
                ConnectionXml = null;
                return;
            }
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(data);
            MemoryStream memoryStream = new MemoryStream(byteArray);
            XmlSerializer serializer = new XmlSerializer(typeof(List<LineConnectionRange>));
            ConnectionXml = new List<LineConnectionRange>((List<LineConnectionRange>)serializer.Deserialize(memoryStream));
        }

        public void DeSerializeVertex(string data)
        {
            if (string.IsNullOrEmpty(data))
            {
                EquipmentXml = null;
                return;
            }
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(data);
            MemoryStream memoryStream = new MemoryStream(byteArray);
            XmlSerializer serializer = new XmlSerializer(typeof(List<EquipmentSerializer>));
            EquipmentXml = new List<EquipmentSerializer>((List<EquipmentSerializer>)serializer.Deserialize(memoryStream));
        }

        public string SerializeLineConnection()
        {
            MemoryStream memoryStream = new MemoryStream();
            XmlSerializer serializer = new XmlSerializer(typeof(List<LineConnectionRange>));
            List<LineConnectionRange> es = new List<LineConnectionRange>(connectionLine);
            serializer.Serialize(memoryStream, es);
            UTF8Encoding encoding = new UTF8Encoding();
            string vertexXml = encoding.GetString(memoryStream.ToArray());
            return vertexXml;
        }

        public string SerializeVertex()
        {
            MemoryStream memoryStream = new MemoryStream();
            XmlSerializer serializer = new XmlSerializer(typeof(List<EquipmentSerializer>));
            List<EquipmentSerializer> es = new List<EquipmentSerializer>(_curveElements);
            serializer.Serialize(memoryStream, es);
            UTF8Encoding encoding = new UTF8Encoding();
            string vertexXml = encoding.GetString(memoryStream.ToArray());
            return vertexXml;
        }

        private int _rangeID { get; set; }
        private int _lineConnectionID { get; set; }
        public void SetGraphic(int? vertexID)
        {
            _rangeID = 0;
            _lineConnectionID = 0;
            Plan = null;
            _VertexID = vertexID;
            Ranges.Clear();
            _curveElements.Clear();
            connectionLine.Clear();
            switch (PlanType)
            {
                case 1:
                    CreateCableBoxLink(null);
                    CreateCable();
                    break;
                case 2:
                    CreateCableBox(null);
                    CreateCableBoxLink(null);
                    break;
                case 3:
                    CreateCableBox(null);
                    CreateCableBoxLink(null);
                    CreateCrosses();
                    CreateCable();
                    break;
            }
            CreateFibre(null);

            IEnumerable<CrossBoxVis> c = from q in _curveElements where q is CableViz || q is CableBoxLinkVis select q;
            foreach (CrossBoxVis item in c)
            {
                foreach (FibreRange fibreRange in item.FibresOne)
                {
                    ConnectOut(fibreRange, false);
                }
            }
            if (_VertexID != vertexID)
            {
                ZeroPoint = Point.Empty;
                Plan = null;
            }
        }

        public void ReCreateConnectorLine(int curveElementID)
        {
            CrossBoxVis c = FindCurveElementByID(curveElementID);
            foreach (FibreRange fibreRange in c.FibresOne)
            {
                connectionLine.RemoveAll(l => l.Fibre1ID == fibreRange.FibreID || l.Fibre2ID == fibreRange.FibreID);
                ConnectionXml.RemoveAll(l => l.Fibre1ID == fibreRange.FibreID || l.Fibre2ID == fibreRange.FibreID);
                ConnectOut(fibreRange, false);
            }
        }

        public void AddRangeBase(RangeBase rangeBase)
        {
            rangeBase.RangeID = _rangeID;
            _rangeID++;
            Ranges.Add(rangeBase);

        }

        public int RemoveRangeBase(RangeBase rangeBase)
        {
            return Ranges.RemoveAll(r => r.RangeID == rangeBase.RangeID);
        }

        public Bitmap Plan { get; private set; }
        public event EventHandler PlanCommit;
        public void DrawVertex(Rectangle rectangle, bool isPrint)
        {
            this.IsPrint = isPrint;
            Rectangle r = GetPlanRectangle();
            Plan = new Bitmap(rectangle.Width, rectangle.Height);
            Graphics graphics = Graphics.FromImage(Plan);
            if (_curveElements.Count == 0)
            {
                Font font = new Font("Arial", 24);
                Brush brushCaption = Brushes.Gray;
                graphics.DrawString("Пусто", font, brushCaption, ZeroPoint.X - 100, ZeroPoint.Y);
            }
            foreach (CrossBoxVis item in _curveElements)
            {
                item.Draw(graphics);
            }

            drawConnection(connectionLine, graphics);
            if (PlanCommit != null) PlanCommit.Invoke(this, EventArgs.Empty);

        }

        public void CreateCableBox(int? cableBoxID)
        {
            if (_VertexID == null) return;
            try
            {
                int i = 1;
                CableBoxesTableAdapter cableBoxesAdapter = new CableBoxesTableAdapter();
                cableBoxesAdapter.ClearBeforeFill = true;
                cableBoxesAdapter.SelectCommandTimeout = Properties.Settings.Default.LongQueryTimeout;
                SimpleOpticNetDB.CableBoxesDataTable CableBoxes = cableBoxesAdapter.GetData(cableBoxID, _VertexID,
                                                                                            (int)CableBoxKinds.CableBox);

                foreach (SimpleOpticNetDB.CableBoxesRow CableItem in CableBoxes.Cast<SimpleOpticNetDB.CableBoxesRow>())
                {
                    CableBoxVis cableBoxVis = new CableBoxVis();
                    cableBoxVis.Vis = this;
                    cableBoxVis.CurveElementKindID = (int)CableBoxKinds.CableBox;
                    cableBoxVis.SetRow(CableItem);
                    cableBoxVis.Index = i;
                    AddEquipments(cableBoxVis);
                    i++;
                }
            }
            catch (Exception error)
            {
                System.Diagnostics.Debug.Write(error.Message);
            }
        }

        public void CreateCableBoxLink(int? cableBoxID)
        {
            if (_VertexID == null) return;
            try
            {
                int i = 1;
                CableBoxesTableAdapter cableBoxesAdapter = new CableBoxesTableAdapter();
                cableBoxesAdapter.ClearBeforeFill = true;
                cableBoxesAdapter.SelectCommandTimeout = Properties.Settings.Default.LongQueryTimeout;
                SimpleOpticNetDB.CableBoxesDataTable CableBoxes = cableBoxesAdapter.GetData(cableBoxID, _VertexID,
                                                                                            (int)CableBoxKinds.CableBoxLink);

                foreach (SimpleOpticNetDB.CableBoxesRow CableItem in CableBoxes.Cast<SimpleOpticNetDB.CableBoxesRow>())
                {
                    CableBoxVis cableBoxVis = new CableBoxLinkVis();
                    cableBoxVis.Vis = this;
                    cableBoxVis.CurveElementKindID = (int)CableBoxKinds.CableBoxLink;
                    cableBoxVis.SetRow(CableItem);
                    cableBoxVis.Index = i;
                    AddEquipments(cableBoxVis);
                    i++;
                }
            }
            catch (Exception error)
            {
                //System.Diagnostics.Debug.Assert();
                System.Diagnostics.Debug.Write(error.Message);
            }

        }

        private void CreateCrosses()
        {
            if (_VertexID == null) return;
            try
            {
                int i = 1;
                EquipmentTableAdapter equipmentTableAdapter = new EquipmentTableAdapter();
                equipmentTableAdapter.ClearBeforeFill = true;
                equipmentTableAdapter.SelectCommandTimeout = Properties.Settings.Default.LongQueryTimeout;
                SimpleOpticNetDB.EquipmentDataTable equipmentDataTable = equipmentTableAdapter.GetData(_VertexID, null);


                foreach (SimpleOpticNetDB.EquipmentRow EquipmentItem in equipmentDataTable.Cast<SimpleOpticNetDB.EquipmentRow>())
                {
                    CrossBoxVis crossBoxVis = new CrossBoxVis();
                    crossBoxVis.Vis = this;
                    crossBoxVis.Enter = 2;
                    crossBoxVis.SetRow(EquipmentItem);
                    crossBoxVis.CurveElementKindID = 3;
                    AddEquipments(crossBoxVis);
                    i++;
                }
            }
            catch (Exception error)
            {
                //System.Diagnostics.Debug.Assert();
                System.Diagnostics.Debug.Write(error.Message);
            }

        }

        private void CreateCable()
        {
            if (_VertexID == null) return;
            try
            {
                int i = 1;
                CableTableAdapter cableTableAdapter = new CableTableAdapter();
                cableTableAdapter.ClearBeforeFill = true;
                cableTableAdapter.SelectCommandTimeout = Properties.Settings.Default.LongQueryTimeout;
                SimpleOpticNetDB.CableDataTable equipmentDataTable = cableTableAdapter.GetData(null, _VertexID, null);


                foreach (SimpleOpticNetDB.CableRow cableItem in equipmentDataTable.Cast<SimpleOpticNetDB.CableRow>())
                {
                    CableViz crossBoxVis = new CableViz();
                    crossBoxVis.Vis = this;
                    crossBoxVis.SetRow(cableItem);
                    crossBoxVis.CurveElementKindID = 1;
                    crossBoxVis.Hint = cableItem.IsHintNull() ? "" : cableItem.Hint ;
                    AddEquipments(crossBoxVis);
                    i++;
                }
            }
            catch (Exception error)
            {
                //System.Diagnostics.Debug.Assert();
                System.Diagnostics.Debug.Write(error.Message);
            }

        }

        public void CreateFibre(List<int> equipList)
        {
            IEnumerable<CrossBoxVis> ranges = null;
            if (equipList == null || equipList.Count == 0)
            {
                ranges = from q in _curveElements select q;
                List<Task> tasks = new List<Task>();
                foreach (CrossBoxVis item in ranges)
                    item.CreateFibre(_VertexID.Value);
            }
        }

        public CrossBoxVis FindCurveElementByID(int equipmentID)
        {
            try
            {
                return (from q in _curveElements where q.ID == equipmentID select q).First();

            }
            catch (Exception)
            {

            }
            return null;

        }

        public List<CrossBoxVis> GetEquipmentByKindID(int KindID)
        {
            try
            {

                return (from q in _curveElements where q.CurveElementKindID == KindID select q).ToList();
            }
            catch (Exception)
            {

            }
            return new List<CrossBoxVis>();

        }

        public List<RangeBase> FindRange(Point point)
        {
            return (from q in Ranges where q.ClickRange(point) && q.Visible select q).ToList();
        }

        public List<RangeBase> FindRangeByFibreID(int fibreID, bool isFree)
        {

            return (from q in Ranges where q.FibreID == fibreID && (!isFree || (q is FibreRange && !((FibreRange)q).ToFibreID.HasValue)) select q).ToList();
        }

        public List<RangeBase> FindRangeByRangeID(int rangeID)
        {

            return (from q in Ranges where q.RangeID == rangeID select q).ToList();
        }

        public void CreateFibreLine(FibreRange fibre1, FibreRange fibre2, bool activeLine, bool isConnectionIn)
        {
            LineConnectionRange lc = new LineConnectionRange(fibre1, fibre2, this, isConnectionIn, CalckHorizontSection) { LineConnectionID = _lineConnectionID };
            _lineConnectionID++;
            lc.LineActivite = activeLine;
            connectionLine.Add(lc);
            fibre1.ToFibreID = fibre2.FibreID;
            fibre1.Status = RangeStatus.Connection;
            fibre2.Status = RangeStatus.Connection;
            fibre2.ToFibreID = fibre1.FibreID;
        }

        public void CreateFibreLine(int fibre1_ID, int fibre2_ID, bool activeLine)
        {
            try
            {
                (from q in connectionLine
                 where
                     (q.Fibre1ID == fibre1_ID && q.Fibre2ID == fibre2_ID) ||
                     (q.Fibre1ID == fibre2_ID && q.Fibre2ID == fibre1_ID)
                 select q).
                    First().LineActivite = activeLine;
                return;
            }
            catch (Exception)
            {
            }
            FibreRange fs1 = null, fs2 = null;
            List<FibreRange> l1 = new List<FibreRange>(from q in Ranges where q.FibreID == fibre1_ID select q as FibreRange);
            List<FibreRange> l2 = new List<FibreRange>(from q in Ranges where q.FibreID == fibre2_ID select q as FibreRange);
            LineConnectionRange lineConnectionRange = null;
            try
            {
                lineConnectionRange = (from q in ConnectionXml
                                                           where
                                                               (q.Fibre1ID == fibre1_ID && q.Fibre2ID == fibre2_ID) ||
                                                               (q.Fibre1ID == fibre2_ID && q.Fibre2ID == fibre1_ID)
                                                           select q).First();
                if (lineConnectionRange != null)
                {
                    fs1 = (from q in l1
                           where
                               q.VirtualConnectionPointOut == lineConnectionRange.Point1 ||
                               q.VirtualConnectionPointOut == lineConnectionRange.Point2
                           select q).First();
                    fs2 = (from q in l2
                           where
                               q.VirtualConnectionPointOut == lineConnectionRange.Point1 ||
                               q.VirtualConnectionPointOut == lineConnectionRange.Point2
                           select q).First();

                    CreateFibreLine(fs1, fs2, activeLine, false);

                    return;
                }
            }
            catch (Exception)
            {
                if (ConnectionXml != null)
                    ConnectionXml.RemoveAll(l => l.Fibre1ID == fibre1_ID && l.Fibre2ID == fibre2_ID);
            }

            int distanse = int.MaxValue;

            foreach (var item1 in l1)
            {
                if (!item1.ToFibreID.HasValue)
                    foreach (var item2 in l2)
                    {
                        if (!item2.ToFibreID.HasValue)
                        {
                            int d =
                                Math.Abs(item1.ConnectionPointOut.Y -
                                         item2.ConnectionPointOut.Y);
                            if (d < distanse)
                            {
                                distanse = d;
                                fs1 = item1;
                                fs2 = item2;
                            }
                        }
                    }
            }

            if (fs1 != null && fs2 != null)
            {
                CreateFibreLine(fs1, fs2, false, false);
            }
        }

        public void ClearConnecion()
        {
            for (int i = 0; i < connectionLine.Count; i++) connectionLine[i].LineActivite = false;
        }

        private void ConnectIn(FibreRange fibreRange, bool activeLine)
        {

            if (fibreRange.Row != null && !fibreRange.Row.IsToFibre_IDNull())
            {
                IEnumerable<RangeBase> connect = from q in Ranges
                                                 where
                                                     q.FibreID == fibreRange.FibreID &&
                                                     ((FibreRange)q).Enter != fibreRange.Enter
                                                 select q;
                if (connect.Count() > 0)
                {
                    FibreRange f2 = (FibreRange)connect.ToList()[0];
                    if (fibreRange.ConnectionPointIn != null && f2.ConnectionPointIn != null)
                    {
                        try
                        {
                            (from q in connectionLine
                             where
                                 (q.Fibre1ID == fibreRange.FibreID && q.Fibre2ID == f2.FibreID) ||
                                 (q.Fibre1ID == f2.FibreID && q.Fibre2ID == fibreRange.FibreID)
                             select q).
                                First().LineActivite = activeLine;
                        }
                        catch (Exception)
                        {
                            CreateFibreLine(fibreRange, f2, true, true);

                        }
                    }
                }
            }
        }

        public void ConnectOut(FibreRange fibreRange, bool activeLine)
        {

            List<int> fibresID = new List<int>();
            Queue<FibreRange> fibres = new Queue<FibreRange>();
            fibresID.Add(fibreRange.FibreID);
            fibres.Enqueue(fibreRange);

            while (fibres.Count() > 0)
            {
                FibreRange f = fibres.Dequeue();
                //     ConnectIn(f, activeLine);
                List<RangeBase> connect = new List<RangeBase>(from q in Ranges
                                                              where q is FibreRange && ((FibreRange)q).Find(f.FibreID, PlanType)
                                                              select q);
                foreach (RangeBase fItem in connect)
                {
                    FibreRange newFibre = fItem as FibreRange;
                    if (newFibre != null && !fibresID.Contains(newFibre.FibreID))
                    {
                        fibres.Enqueue(newFibre);
                        fibresID.Add(newFibre.FibreID);
                        CreateFibreLine(f.FibreID, newFibre.FibreID, activeLine);
                    }
                }
            }
        }

        public List<RangeBase> GetRangeActive()
        {
            return (from q in Ranges where q.Status == RangeStatus.Active select q).ToList();
        }
        public Rectangle GetPlanRectangle()
        {
            int xMax = int.MinValue;
            int xMin = int.MaxValue;

            int yMax = int.MinValue;
            int yMin = int.MaxValue;

            foreach (RangeBase item in Ranges)
            {
                if (item.Location.X < xMin) xMin = item.Location.X;
                if (item.Location.X + item.LocationSize.Width > xMax) xMax = item.Location.X + item.LocationSize.Width;

                if (item.Location.Y < yMin) yMin = item.Location.Y;
                if (item.Location.Y + item.LocationSize.Height > yMax) yMax = item.Location.Y + item.LocationSize.Height;
            }

            Rectangle rectangle = new Rectangle(new Point(xMin, yMin), new Size(xMax - xMin, yMax - yMin));

            return rectangle;
        }
        public void PlanToCenter(Point ViewCenter)
        {
            Rectangle r = GetPlanRectangle();
            Point c = r.Location + new Size(r.Width / 2, r.Height / 2);
            Size s = new Size(ViewCenter.X - c.X, ViewCenter.Y - c.Y);
            ZeroPoint += s;
        }

        private void drawConnection(List<LineConnectionRange> listConnection, Graphics G)
        {
            if (AllConnection || IsPrint)
                listConnection.ForEach(rectagle => rectagle.Draw(G));
            else
            {
                (from q in listConnection where q.LineActivite select q).ToList().ForEach(rectagle => rectagle.Draw(G));
            }
        }

        public List<SimpleOpticNetDB.FibreRow> GetFibreFromDB(int CurveElementID, int? FibreID)
        {
            FibreTableAdapter fibreTableAdapter = new FibreTableAdapter();
            fibreTableAdapter.ClearBeforeFill = true;
            fibreTableAdapter.SelectCommandTimeout = Properties.Settings.Default.LongQueryTimeout;
            return fibreTableAdapter.GetData(CurveElementID, null, FibreID, false, _VertexID).Cast<SimpleOpticNetDB.FibreRow>().ToList();
        }

        public int CalckHorizontSection(FibreRange fibreRange1, FibreRange fibreRange2)
        {
            if (fibreRange1.Enter == 1 && fibreRange2.Enter == 1)
            {
                int numberFibre = fibreRange1.VirtualConnectionPointOut.Y > fibreRange2.VirtualConnectionPointOut.Y
                                      ? fibreRange1.Number
                                      : fibreRange2.Number;

                int y = fibreRange1.VirtualConnectionPointOut.Y > fibreRange2.VirtualConnectionPointOut.Y
                            ? fibreRange1.VirtualConnectionPointOut.Y
                            : fibreRange2.VirtualConnectionPointOut.Y;
                return y + (15 + numberFibre * 4);
            }

            if (fibreRange1.Enter == 2 && fibreRange2.Enter == 2)
            {
                int numberFibre = fibreRange1.VirtualConnectionPointOut.Y < fibreRange2.VirtualConnectionPointOut.Y
                                      ? fibreRange1.Number
                                      : fibreRange2.Number;

                int y = fibreRange1.VirtualConnectionPointOut.Y < fibreRange2.VirtualConnectionPointOut.Y
                            ? fibreRange1.VirtualConnectionPointOut.Y
                            : fibreRange2.VirtualConnectionPointOut.Y;
                return y - (15 + numberFibre * 4);
            }

            if (fibreRange1.Enter != fibreRange2.Enter)
                try
                {
                    int fCount1 = FindCurveElementByID(fibreRange1.CurveElementID).FibresOne.Count();
                    int fCount2 = FindCurveElementByID(fibreRange2.CurveElementID).FibresOne.Count();

                    int numberFibre = fCount1 < fCount2 ? fibreRange1.Number : fibreRange2.Number;
                    int enter = fCount1 < fCount2 ? fibreRange1.Enter : fibreRange2.Enter;

                    int step =
                        (Math.Abs(fibreRange1.VirtualConnectionPointOut.Y - fibreRange2.VirtualConnectionPointOut.Y) - 5)/
                        (fCount1 < fCount2 ? fCount1 : fCount2);
                    
                    int y = fCount1 < fCount2
                                ? fibreRange1.VirtualConnectionPointOut.Y
                                : fibreRange2.VirtualConnectionPointOut.Y;
                    if (enter == 2)
                        return y - (5 + numberFibre * step);
                    else
                        return y + (5 + numberFibre * step);
                }
                catch (Exception)
                {
                }

            return (fibreRange1.VirtualConnectionPointOut.Y + fibreRange2.VirtualConnectionPointOut.Y) / 2;
        }
    }
    }